<template>
  <!-- 无障碍焦点指示器组件 -->
  <transition name="focus-indicator">
    <div 
      v-if="visible"
      class="focus-indicator"
      :class="{
        'custom-shape': customShape,
        'pulse': pulse,
        'ring': ring,
        'glow': glow,
        'high-contrast': $accessibility?.service?.isHighContrastEnabled(),
        [`size-${size}`]: true
      }"
      :style="indicatorStyle"
      aria-hidden="true"
    >
      <div class="focus-indicator-inner" v-if="customShape"></div>
    </div>
  </transition>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';

// 定义组件属性
const props = defineProps({
  // 焦点指示器颜色
  color: {
    type: String,
    default: 'var(--color-focus, #1976d2)'
  },
  
  // 焦点指示器尺寸变体: small, medium, large, xlarge
  size: {
    type: String,
    default: 'medium',
    validator: (value) => ['small', 'medium', 'large', 'xlarge'].includes(value)
  },
  
  // 是否启用脉冲动画
  pulse: {
    type: Boolean,
    default: true
  },
  
  // 是否启用环形效果
  ring: {
    type: Boolean,
    default: false
  },
  
  // 是否启用发光效果
  glow: {
    type: Boolean,
    default: true
  },
  
  // 是否使用自定义形状
  customShape: {
    type: Boolean,
    default: false
  },
  
  // 边框宽度
  borderWidth: {
    type: Number,
    default: 3
  },
  
  // 额外的内边距
  extraPadding: {
    type: Number,
    default: 4
  },
  
  // 是否只在键盘导航时显示
  keyboardOnly: {
    type: Boolean,
    default: true
  },
  
  // 是否在鼠标操作后隐藏
  hideOnMouse: {
    type: Boolean,
    default: true
  },
  
  // 鼠标操作后隐藏的延迟（毫秒）
  hideDelay: {
    type: Number,
    default: 100
  },
  
  // 是否启用动画
  animationEnabled: {
    type: Boolean,
    default: true
  },
  
  // 动画持续时间（毫秒）
  animationDuration: {
    type: Number,
    default: 300
  }
});

// 定义组件事件
const emit = defineEmits(['show', 'hide', 'update']);

// 响应式数据
const visible = ref(false);
const focusedElement = ref(null);
const indicatorStyle = ref({});
let lastFocusTime = 0;
let lastKeyboardTime = 0;
let hideTimer = null;
let animationFrame = null;

// 是否通过键盘导航获得焦点
const isKeyboardNavigation = computed(() => {
  if (!props.keyboardOnly) return true;
  
  // 检查最后一次键盘操作时间是否在最近的焦点事件之后
  const now = Date.now();
  const timeDiff = now - lastKeyboardTime;
  
  // 如果键盘操作在焦点事件后的500毫秒内，则认为是键盘导航
  return timeDiff < 500;
});

// 计算指示器样式
const calculateIndicatorStyle = (element) => {
  if (!element) return {};
  
  // 获取元素的位置和尺寸
  const rect = element.getBoundingClientRect();
  
  // 计算指示器的位置和尺寸，添加额外的内边距
  const left = rect.left - props.extraPadding;
  const top = rect.top - props.extraPadding;
  const width = rect.width + props.extraPadding * 2;
  const height = rect.height + props.extraPadding * 2;
  
  return {
    left: `${left}px`,
    top: `${top}px`,
    width: `${width}px`,
    height: `${height}px`,
    borderColor: props.color,
    borderWidth: `${props.borderWidth}px`,
    animationDuration: props.animationEnabled ? `${props.animationDuration}ms` : '0ms'
  };
};

// 更新焦点指示器
const updateFocusIndicator = (element) => {
  if (!element || !element.matches(':focus')) return;
  
  // 存储获得焦点的元素
  focusedElement.value = element;
  lastFocusTime = Date.now();
  
  // 清除之前的隐藏定时器
  if (hideTimer) {
    clearTimeout(hideTimer);
    hideTimer = null;
  }
  
  // 检查是否应该显示
  if (!isKeyboardNavigation.value && props.keyboardOnly) {
    visible.value = false;
    return;
  }
  
  // 计算并更新样式
  animationFrame = requestAnimationFrame(() => {
    if (element.isConnected) { // 确保元素仍然在DOM中
      indicatorStyle.value = calculateIndicatorStyle(element);
      visible.value = true;
      
      // 触发显示事件
      emit('show');
      emit('update', { element, style: indicatorStyle.value });
    }
  });
};

// 隐藏焦点指示器
const hideFocusIndicator = () => {
  // 只有在鼠标操作时才隐藏
  if (!props.hideOnMouse) return;
  
  hideTimer = setTimeout(() => {
    if (!isKeyboardNavigation.value) {
      visible.value = false;
      focusedElement.value = null;
      emit('hide');
    }
  }, props.hideDelay);
};

// 处理焦点事件
const handleFocus = (event) => {
  // 排除不需要显示焦点指示器的元素
  const skipElements = ['body', 'html', 'input[type="hidden"]'];
  const element = event.target;
  
  if (skipElements.some(selector => element.matches(selector))) {
    return;
  }
  
  // 检查元素是否有自定义焦点样式
  if (element.dataset.skipFocusIndicator) {
    return;
  }
  
  // 更新焦点指示器
  updateFocusIndicator(element);
};

// 处理失焦事件
const handleBlur = () => {
  // 延迟隐藏，以便在元素之间切换焦点时保持可见
  setTimeout(() => {
    // 检查文档中是否还有获得焦点的元素
    const activeElement = document.activeElement;
    if (!activeElement || activeElement === document.body) {
      visible.value = false;
      focusedElement.value = null;
      emit('hide');
    }
  }, 10);
};

// 处理键盘事件
const handleKeydown = () => {
  lastKeyboardTime = Date.now();
  
  // 如果当前有焦点元素，显示指示器
  if (document.activeElement && document.activeElement !== document.body) {
    updateFocusIndicator(document.activeElement);
  }
};

// 处理鼠标事件
const handleMousedown = () => {
  // 重置键盘导航标记
  lastKeyboardTime = 0;
  
  // 隐藏焦点指示器
  hideFocusIndicator();
};

// 处理滚动事件
const handleScroll = () => {
  // 如果有焦点元素，更新指示器位置
  if (focusedElement.value && visible.value) {
    animationFrame = requestAnimationFrame(() => {
      if (focusedElement.value?.isConnected) {
        indicatorStyle.value = calculateIndicatorStyle(focusedElement.value);
        emit('update', { element: focusedElement.value, style: indicatorStyle.value });
      }
    });
  }
};

// 处理调整大小事件
const handleResize = () => {
  // 如果有焦点元素，更新指示器位置
  if (focusedElement.value && visible.value) {
    animationFrame = requestAnimationFrame(() => {
      if (focusedElement.value?.isConnected) {
        indicatorStyle.value = calculateIndicatorStyle(focusedElement.value);
        emit('update', { element: focusedElement.value, style: indicatorStyle.value });
      }
    });
  }
};

// 监听无障碍设置变化
const watchAccessibilitySettings = () => {
  // 这里可以添加对无障碍设置的监听
  // 例如高对比度模式的变化
};

// 生命周期钩子
onMounted(() => {
  // 添加事件监听
  document.addEventListener('focusin', handleFocus, true);
  document.addEventListener('focusout', handleBlur, true);
  document.addEventListener('keydown', handleKeydown, true);
  document.addEventListener('mousedown', handleMousedown, true);
  window.addEventListener('scroll', handleScroll, true);
  window.addEventListener('resize', handleResize, true);
  
  // 初始化时检查当前焦点
  setTimeout(() => {
    if (document.activeElement && document.activeElement !== document.body) {
      updateFocusIndicator(document.activeElement);
    }
  }, 100);
});

onUnmounted(() => {
  // 清除定时器和动画帧
  if (hideTimer) {
    clearTimeout(hideTimer);
  }
  
  if (animationFrame) {
    cancelAnimationFrame(animationFrame);
  }
  
  // 移除事件监听
  document.removeEventListener('focusin', handleFocus, true);
  document.removeEventListener('focusout', handleBlur, true);
  document.removeEventListener('keydown', handleKeydown, true);
  document.removeEventListener('mousedown', handleMousedown, true);
  window.removeEventListener('scroll', handleScroll, true);
  window.removeEventListener('resize', handleResize, true);
  
  // 重置状态
  visible.value = false;
  focusedElement.value = null;
});

// 监听属性变化
watch(() => props.color, (newColor) => {
  if (indicatorStyle.value) {
    indicatorStyle.value.borderColor = newColor;
  }
});

watch(() => props.animationEnabled, (enabled) => {
  if (indicatorStyle.value) {
    indicatorStyle.value.animationDuration = enabled ? `${props.animationDuration}ms` : '0ms';
  }
});

// 导出公共方法
defineExpose({
  show: () => {
    visible.value = true;
    emit('show');
  },
  
  hide: () => {
    visible.value = false;
    emit('hide');
  },
  
  toggle: () => {
    visible.value = !visible.value;
    if (visible.value) {
      emit('show');
    } else {
      emit('hide');
    }
  },
  
  update: () => {
    if (focusedElement.value) {
      updateFocusIndicator(focusedElement.value);
    }
  },
  
  getFocusedElement: () => focusedElement.value
});
</script>

<style scoped>
.focus-indicator {
  position: fixed;
  z-index: var(--z-focus-indicator, 999999);
  pointer-events: none;
  box-sizing: border-box;
  border-style: solid;
  border-radius: 4px;
  transition: opacity 0.2s ease, transform 0.2s ease;
  opacity: 0;
  transform: scale(0.95);
}

/* 过渡动画 */
.focus-indicator-enter-active,
.focus-indicator-leave-active {
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.focus-indicator-enter-from,
.focus-indicator-leave-to {
  opacity: 0;
  transform: scale(0.95);
}

.focus-indicator-enter-to,
.focus-indicator-leave-from {
  opacity: 1;
  transform: scale(1);
}

/* 尺寸变体 */
.focus-indicator.size-small {
  border-width: 2px;
  border-radius: 3px;
}

.focus-indicator.size-medium {
  border-width: 3px;
  border-radius: 4px;
}

.focus-indicator.size-large {
  border-width: 4px;
  border-radius: 6px;
}

.focus-indicator.size-xlarge {
  border-width: 5px;
  border-radius: 8px;
}

/* 脉冲动画 */
.focus-indicator.pulse::after {
  content: '';
  position: absolute;
  top: -5px;
  left: -5px;
  right: -5px;
  bottom: -5px;
  border: 2px solid currentColor;
  border-radius: inherit;
  opacity: 0.7;
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0% {
    transform: scale(0.95);
    opacity: 0.7;
  }
  50% {
    transform: scale(1.05);
    opacity: 0.3;
  }
  100% {
    transform: scale(0.95);
    opacity: 0.7;
  }
}

/* 环形效果 */
.focus-indicator.ring {
  background-color: transparent;
  border-color: currentColor;
  border-style: solid;
  border-radius: 50%;
  transform-origin: center;
  animation: ring-expand 0.3s ease-out;
}

@keyframes ring-expand {
  from {
    transform: scale(0.8);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}

/* 发光效果 */
.focus-indicator.glow {
  box-shadow: 0 0 8px currentColor;
}

/* 自定义形状 */
.focus-indicator.custom-shape {
  background-color: transparent;
  border: none;
  box-shadow: none;
}

.focus-indicator-inner {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border: 2px dashed currentColor;
  border-radius: 8px;
  animation: dash 2s linear infinite;
}

@keyframes dash {
  to {
    stroke-dashoffset: -1000;
  }
}

/* 高对比度模式 */
.focus-indicator.high-contrast {
  border-width: 4px;
  box-shadow: 0 0 0 2px #000;
  border-style: solid;
}

.focus-indicator.high-contrast.pulse::after {
  border-width: 3px;
}

/* 减少动画模式 */
@media (prefers-reduced-motion: reduce) {
  .focus-indicator {
    transition: none;
    opacity: 1 !important;
    transform: scale(1) !important;
  }
  
  .focus-indicator.pulse::after {
    animation: none;
  }
  
  .focus-indicator.ring {
    animation: none;
  }
  
  .focus-indicator.custom-shape .focus-indicator-inner {
    animation: none;
  }
}

/* 打印样式 */
@media print {
  .focus-indicator {
    display: none !important;
  }
}
</style>